import socket
import select
import threading
import os
import tkinter as tk
from tkinter import *
from tkinter import scrolledtext
import tkinter.messagebox
import time

##服务器

class App(tk.Tk):

    def __init__(self):
        super().__init__()
        self.ip=StringVar()
        self.port=StringVar()
        self.clients={}
        self.inputs=[]
        self.outputs=[]
        self.s=None
        self.tkgui()

    def tkgui(self):
        self.title('socketserver')
        self.geometry('600x600')
        self.l_ip=tk.Label(self,text='服务器ip:')
        self.l_ip.grid(row=0,column=0,padx=10,pady=10,sticky=tk.E)
        self.e_ip=tk.Entry(self,textvariable=self.ip)
        self.e_ip.grid(row=0,column=1,padx=10,pady=10,sticky=tk.W)

        self.l_port=tk.Label(self,text='服务器端口:')
        self.l_port.grid(row=1,column=0,padx=10,pady=10,sticky=tk.E)
        self.e_port=tk.Entry(self,textvariable=self.port)
        self.e_port.grid(row=1,column=1,padx=10,pady=10,sticky=tk.W)

        self.btnst=tk.Button(self,text='开启服务',command=self.cthread)
        self.btnst.grid(row=2,column=0,padx=5,pady=5,sticky=tk.E)
        self.btnsp=tk.Button(self,text='断开服务',command=self.stopServer)
        self.btnsp.grid(row=2,column=1,padx=5,pady=5,sticky=tk.W)
        self.btnsp.configure(state='disable')
        
        self.sW=80
        self.sH=30
        self.scr=scrolledtext.ScrolledText(self,width=self.sW,height=self.sH,wrap=tk.WORD)
        self.scr.grid(row=3,column=0,columnspan=2)
   
    def tcpserve(self):

    ##    if not os.path.exists('d:/chat/'):
    ##        os.makedirs('d:/chat/')
        
        while True:
            try:
                stdinput, stdoutput, stderr = select.select(self.inputs, self.outputs, self.inputs)
            except:
                print('断开')
                self.clients.clear()
                return
            for obj in stdinput:
                if obj is self.s:
                    try:
                        c,addr=self.s.accept()
                    except:
                        print('断开')
                        return
                    self.inputs.append(c)
                    self.clients[addr]=c
                    for l in self.clients:
                        try:
                            self.clients[l].sendall('{}已登入'.format(str(addr)).encode('utf-8'))
                        except:
                            pass
                    print('{}已登入'.format(str(addr)))
                    self.scr.insert("insert",'{}已登入\n'.format(str(addr)))
                    self.scr.see(tk.END)
                    self.scr.update()

                else:
                    
                    try:
                        acceptmsg=str(obj.recv(1024),encoding='utf-8')
             
                        print(''.join([acceptmsg,' 客户端口：',str(addr[1])]))
                        
                        accptdata=''.join([acceptmsg,' 客户端口：',str(addr[1])])
                        accptdata=accptdata+'\n'
                        for k in self.clients:
                            self.clients[k].sendall(accptdata.encode('utf-8'))
                        self.scr.insert("insert",accptdata)
                        self.scr.see(tk.END)
                        self.scr.update()
                        
                        if obj not in self.outputs:  
                                self.outputs.append(obj)
                    except ConnectionResetError:
                        adr=obj.getpeername()
                        self.clients={k:v for k,v in self.clients.items() if k!=adr }
                        for b in self.clients:
                            #try:
                            self.clients[b].sendall('{}已退出'.format(str(adr)).encode('utf-8'))
                            print('{}已退出'.format(str(adr)))
                        self.scr.insert("insert",'{}已退出\n'.format(str(adr)))
                        self.scr.see(tk.END)
                        self.scr.update()
                            #except:
                                #print('err')
                        if not self.clients:
                            print('最后一位{}已退出'.format(str(adr)))
                            self.scr.insert("insert",'最后一位：{}已退出\n'.format(str(adr)))
                            self.scr.see(tk.END)
                            self.scr.update()
                        self.inputs.remove(obj)
                            

    ##        with open('d:/chat/c.txt','r') as f:
    ##            accptall=f.read()
    ##            sendmsg=accptall
    ##        c.sendall(sendmsg.encode('utf-8'))
    ##    c.close()


    def main(self):

        self.s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
##        host='127.0.0.1'
##        port=8800
        self.host=self.ip.get()
        self.e_port=self.port.get()
        if not self.host:
            tkinter.messagebox.showinfo('提示','请输入IP地址！')
            self.scr.insert("insert",'开启失败\n')
            self.scr.see(tk.END)
            self.scr.update()
            return
        
        if not self.e_port:
            tkinter.messagebox.showinfo('提示','请输入端口！')
            self.scr.insert("insert",'开启失败\n')
            self.scr.see(tk.END)
            self.scr.update()
            return
        try:
            self.e_port=int(self.e_port)
        except:
            print('无效端口！')
            tkinter.messagebox.showinfo('提示','无效端口！')
            self.scr.insert("insert",'开启失败\n')
            self.scr.see(tk.END)
            self.scr.update()
            return
        ##s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1024)
        try:
            self.s.bind((self.host,self.e_port))
        except:
            print('开启失败')
            self.scr.insert("insert",'开启失败\n')
            self.scr.see(tk.END)
            self.scr.update()
            tkinter.messagebox.showinfo('提示','开启失败,IP或端口错误！')
            return
        self.s.listen(5)
        self.inputs = [self.s]
        self.btnst.configure(state='disable')
        self.btnsp.configure(state='normal')
        self.tcpserve()
       
        
    def cthread(self):
        t=threading.Thread(target=self.main)
        t.start()
        #t.join()
        print('已开启')
        self.scr.insert("insert",'已开启\n')
        self.scr.see(tk.END)
        self.scr.update()

    def stopServer(self):
        self.scr.insert("insert",'已断开\n')
        self.scr.see(tk.END)
        self.scr.update()
        print('已断开')
        self.s.close()
        self.clients.clear()
        self.inputs.clear()
        self.outputs.clear()
        self.btnst.configure(state='normal')
        self.btnsp.configure(state='disable')
    

if __name__=='__main__':
        
    app=App()
    app.mainloop()

